#include "../Common.h"
#include "MemoryManager.h"
#include "SmallObjAllocator.h"
#include "FixedAllocator.h"

using namespace Stray;
using namespace Stray::Core;

SmallObjAllocator::SmallObjAllocator(size_t pageSize, size_t maxObjectSize, size_t alignSize)
	:pAllocators_(0)
	,maxSize_(maxObjectSize)
	,alignSize_(alignSize)
{
	assert(0 != alignSize_);
	const size_t allocCount = getAllocatorIndex(maxSize_, alignSize_) + 1;
	pAllocators_ = new FixedAllocator[allocCount];
	for(size_t i = 0; i < allocCount; ++i)
        pAllocators_[i].initialize((i+1) * alignSize_, pageSize);
}

SmallObjAllocator::~SmallObjAllocator()
{
	delete [] pAllocators_;
}

void* SmallObjAllocator::allocate(size_t size)
{
	if(size > maxSize_) return MemoryManager::getInstance().generalAllocate(size);

	assert(pAllocators_ != 0);
	if(size == 0) size = 1;
	const Uint32 i = getAllocatorIndex(size, alignSize_);
	assert(i < getAllocatorIndex(maxSize_, alignSize_) + 1);

	assert(pAllocators_[i].blockSize() >= size);
	assert(pAllocators_[i].blockSize() < size + alignSize_);

	return pAllocators_[i].allocate();
}

void SmallObjAllocator::deallocate(void* p, size_t size)
{
	if(p == 0) return;
	if(size > maxSize_)
	{
		MemoryManager::getInstance().generalDeallocate(p);
		return;
	}

	assert(pAllocators_ != 0);
	if(size == 0) size = 1;
	const Uint32 i = getAllocatorIndex(size, alignSize_);
	assert(i < getAllocatorIndex(maxSize_, alignSize_) + 1);

	assert(pAllocators_[i].blockSize() >= size);
	assert(pAllocators_[i].blockSize() < size + alignSize_);

	Bool result = pAllocators_[i].deallocate(p, 0);
	assert(result);
}